﻿using System;

namespace VideoStore.Services.Translation.Base
{
    /// <summary>
    /// Base class for all translators.
    /// This class uses a mix of strategy pattern and template method pattern
    /// </summary>
    public abstract class BaseTranslator : ITranslator
    {
        #region Implementation of ITranslator

        /// <summary>
        /// Translates a DTO into a new domain entity.
        /// </summary>
        /// <typeparam name="TDto">The type of the dto.</typeparam>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="dto">The dto.</param>
        /// <returns></returns>
        public TEntity TranslateToEntity<TDto, TEntity>(TDto dto)
            where TDto : class
            where TEntity : class
        {
            var concreteEntity = Activator.CreateInstance(typeof(TEntity));
            var entity = TranslateToConcreteEntity(dto, (TEntity)concreteEntity);
            return entity;
        }

        /// <summary>
        /// Translates to concrete entity.
        /// </summary>
        /// <typeparam name="TDto">The type of the dto.</typeparam>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <param name="dto">The dto.</param>
        /// <param name="concreteEntity">The concrete entity.</param>
        /// <returns></returns>
        public abstract TEntity TranslateToConcreteEntity<TDto, TEntity>(TDto dto, TEntity concreteEntity)
            where TEntity : class;

        /// <summary>
        /// Translates to concrete dto.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <typeparam name="TDto">The type of the dto.</typeparam>
        /// <param name="entity">The entity.</param>
        /// <param name="concreteDto">The concrete dto.</param>
        /// <returns></returns>
        public abstract TDto TranslateToConcreteDto<TEntity, TDto>(TEntity entity, TDto concreteDto) where TDto : class;

        /// <summary>
        /// Translates a domain entity into a new DTO.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <typeparam name="TDto">The type of the dto.</typeparam>
        /// <param name="entity">The entity.</param>
        /// <returns></returns>
        public TDto TranslateToDto<TEntity, TDto>(TEntity entity)
            where TDto : class
            where TEntity : class
        {
            var concreteDto = Activator.CreateInstance(typeof(TDto));
            var dto = TranslateToConcreteDto(entity, (TDto)concreteDto);
            return dto;
        }

        #endregion
    }
}